<template>
  <div>控制并发 源码 express-system 执行 'node ./bin/demo.js'</div>
</template>

<script>
function f(myRequest) {
  return new Promise((r, j) => {
    fetch(myRequest)
      .then((response) => {
        if (response.status === 200) {
          return response.json();
        } else {
          throw new Error("Something went wrong on api server!");
        }
      })
      .then((response) => {
        r(response);
      })
      .catch((error) => {
        console.error(error);
      });
  });
}
export default {
  created() {
    // this.awaitFun();
    // this.asyncPool();
    this.retry(this.getData);
    // this.myGetData(f("http://localhost:7001"), 1000, 3);
    // this.myGetData(this.getData, 5, 1000);
  },
  methods: {
    /**
     * 每隔一秒中打印一个数字
     */
    async awaitFun() {
      // 方案一
      // for (let i = 0; i < 10; i++) {
      //   setTimeout(() => {
      //     console.log(i);
      //   }, i * 1000);
      // }

      // 方案二
      function f(i) {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve(i);
          }, 1000);
        });
      }
      for (let i = 0; i < 10; i++) {
        await f(i);
      }
    },

    /**
     * 控制并发数量 每次执行3个并发任务
     */
    async asyncPool() {
      function foo(i) {
        return new Promise((r, j) => {
          setTimeout(() => {
            // if (Math.random() >= 0.5) {
            //   r(i);
            // } else {
            //   j(i);
            // }

            r(i);
          }, 1000);
        });
      }

      let arr = [];
      for (let i = 1; i <= 30; i++) {
        arr.push("http://localhost:7001");
      }
      let data = await this.asyncPool2(10, arr, f);
      console.log(data);
    },
    async asyncPool2(poolLimit, array, iteratorFn) {
      const ret = []; // 存储所有的异步任务
      const executing = []; // 存储正在执行的异步任务
      let index = 0;
      for (const item of array) {
        index++;
        // 调用iteratorFn函数创建异步任务
        console.log(1);
        const p = Promise.resolve().then(
          () => (console.log(2), iteratorFn(item, array))
        );
        console.log(3);
        ret.push(p); // 保存新的异步任务

        // 当poolLimit值小于或等于总任务个数时，进行并发控制
        if (poolLimit <= array.length) {
          // 当任务完成后，从正在执行的任务数组中移除已完成的任务
          const e = p.then(
            () => (console.log(4), executing.splice(executing.indexOf(e), 1))
          );
          executing.push(e); // 保存正在执行的异步任务
          if (executing.length >= poolLimit) {
            console.log("index", index);
            await Promise.race(executing); // 等待较快的任务执行完成
          }
        }
      }

      return Promise.all(ret);
    },
    /**
     * Promise.retry
     *  请求失败3次才是真正失败
     */
    async retry(fn) {
      let count = 0;
      function tool(fn) {
        fn("http://localhost:7001")
          .then((res) => {
            console.log(res);
          })
          .catch((e) => {
            console.log(`还有 ${3 - count} 次尝试`);
            if (3 == count) {
              reject(erro);
            } else {
              count++;
              setTimeout(tool(fn));
            }
          });
      }
      tool(fn);
    },
    myGetData(getData, times, delay) {
      return new Promise(function (resolve, reject) {
        function attempt() {
          getData("http://localhost:7001")
            .then(resolve)
            .catch(function (erro) {
              console.log(`还有 ${times} 次尝试`);
              if (0 == times) {
                reject(erro);
              } else {
                times--;
                setTimeout(attempt(), delay);
              }
            });
        }
        attempt();
      });
    },
    getData(myRequest) {
      let p = new Promise(function (resolve, reject) {
        fetch(myRequest)
          .then((response) => {
            if (response.status === 200) {
              return response.json();
            } else {
              throw new Error("Something went wrong on api server!");
            }
          })
          .then((response) => {
            resolve(response);
          })
          .catch((error) => {
            reject(error);
          });
      });
      return p;
    },
  },
};
</script>

<style lang="less" scoped></style>
